package com.eascs.admin.o2o.loan.notify.common;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.dubbo.config.annotation.Reference;
import com.eascs.admin.o2o.generation.service.O2oGenerationService;
import com.eascs.admin.o2o.internal.controller.PayMentController;
import com.eascs.admin.o2o.internal.dao.WfTypeStatusDao;
import com.eascs.admin.o2o.internal.entity.LoanapplyExpand;
import com.eascs.admin.o2o.internal.entity.WfTypeStatus;
import com.eascs.admin.o2o.internal.service.LoanapplyExpandService;
import com.eascs.admin.o2o.internal.util.BaseUserUtil;
import com.eascs.admin.o2o.internal.util.StatusContexts;
import com.eascs.admin.o2o.loan.entity.O2oLoanapplyEntity;
import com.eascs.admin.o2o.loan.notify.O2OMsgNotifyService;
import com.eascs.admin.o2o.loan.service.O2oLoanapplyService;
import com.eascs.admin.o2o.notify.dao.WFStatusDao;
import com.eascs.admin.o2o.notify.entity.WFStatus;
import com.eascs.admin.o2o.specialInterview.service.O2OSpecialInterviewService;
import com.eascs.afterloan.service.AdvanceSettleService;
import com.eascs.afterloancheck.dao.LoanCheckDao;
import com.eascs.app.log.Logger;
import com.eascs.app.log.LoggerFactory;
import com.eascs.brand.dao.O2oBrandDao;
import com.eascs.brand.dao.O2oPartnerDao;
import com.eascs.demand.service.TicketMainApplyService;
import com.eascs.deploy.dao.DeployFileDao;
import com.eascs.message.service.impl.O2oMessageServiceImpl;
import com.eascs.notify.mail.MailNotifier;
import com.eascs.paymentdetail.service.O2oTransferAccountService;
import com.eascs.workflow.common.entity.wf.ProcessTaskMain;
import com.eascs.workflow.common.entity.wf.ProcessTemplate;
import com.eascs.workflow.common.service.sys.SysPermissionService;
import com.eascs.workflow.common.vo.ModelResult;
import com.eascs.workflow.common.vo.WFNotifyParam;

/**
 * 工作流通知接口
 */
public abstract class O2OWFServiceBase {
	private static Logger log = LoggerFactory.getLogger(O2OWFService.class);
	protected Map<String, O2OMsgNotifyService> serviceMap = new HashMap<String, O2OMsgNotifyService>();

	@Inject
	TicketMainApplyService ticketMainApplyService;
	@Autowired
	BaseUserUtil baseUserUtil;
	@Autowired
	private WFStatusDao wfStatusDao;
	@Autowired
	private O2oLoanapplyService o2oLoanapplyService;
	@Autowired
	private O2oMessageServiceImpl o2oMessageServiceImpl;
	@Autowired
	private PayMentController payMentController;
	@Autowired
	private WfTypeStatusDao wfTypeStatusDao;
	@Autowired
	O2oPartnerDao o2oPartnerDao;
	@Autowired
	O2oBrandDao o2oBrandDao;
	@Autowired
	AdvanceSettleService advanceSettleService;
	@Autowired
	LoanCheckDao loanCheckDao;
	@Autowired
	O2OSpecialInterviewService o2OSpecialInterviewService;
	@Reference
	SysPermissionService sysPermissionService;
	@Reference
	private MailNotifier mailNotifier;
	@Autowired
	O2oGenerationService generationService;
	@Autowired
	O2oTransferAccountService o2oTransferAccountService;
	@Autowired
	DeployFileDao deployFileDao;
	@Autowired
	private LoanapplyExpandService loanapplyExpandService;

	public abstract ModelResult<Boolean> wfNotify(WFNotifyParam notifyParam);

	public ModelResult<Boolean> before(WFNotifyParam notifyParam) {
		// 插入流程明细表
		insertWfStatus(notifyParam);
		String wfType = getWfType(notifyParam);
		// 修改流程主状态表
		WfTypeStatus wfTypeStatus = wfTypeStatusDao.getByLoanapplyNoAndWfType(notifyParam.getReferId(), wfType);
		if (notifyParam.getProcessStatus() == ProcessTaskMain.PROECESS_STATUS_HANDING) { // 第一次流程调用，处理中的新增,其他过程中不做处理
			if (wfTypeStatus == null) {
				updateWftypeStatus(wfTypeStatus, notifyParam, wfType);
			} else if (StatusContexts.O2O_NEW.equals(wfTypeStatus.getWfStatus())) {
				updateWftypeStatus(wfTypeStatus, notifyParam, wfType);
			}
		} else {
			updateWftypeStatus(wfTypeStatus, notifyParam, wfType);
		}
		return new ModelResult<Boolean>().withModel(Boolean.TRUE);
	}

	public ModelResult<Boolean> after(WFNotifyParam notifyParam, O2oLoanapplyEntity loanapplyEntity) {
		if (loanapplyEntity != null) {// 如果是新系统的数据这个可以执行，老系统数据不行
			int effectRow = o2oLoanapplyService.updateEntityById(loanapplyEntity);
			if (effectRow <= 0) {
				log.error("billCode:[{}],更新贷款主表状态失败", loanapplyEntity.getBillCode());
				throw new RuntimeException("更新贷款主表状态失败");
			} 
//			else {
//				/**
//				 * 国安村镇银行的，自动启动保证金管理费流程(流程走到最后，更新了主表状态再来启动保证金管理费)
//				 */
//				if (notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_BANK_REPORT) || notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_BANK_REPORT_FQ)) {// 如果是国安村镇的面签申报，
//					if (StatusContexts.O2O_BANKTYPE_GACZ.equals(loanapplyEntity.getBankLoanName())) {
//						String wfType = getWfType(notifyParam);
//						PayMentForm payform = new PayMentForm();
//						payform.setBillCode(loanapplyEntity.getBillCode());
//						payform.setLoanapplyNo(loanapplyEntity.getLoanapplyNo());
//						payform.setWfType(wfType);
//						BaseRestResult<String> result = payMentController.order(payform);
//						log.info("启动保证金管理费流程结构,result：[{}]", result.getData());
//					}
//				}
//			}
			log.info("billCode:[{}],更新贷款主表状态成功", loanapplyEntity.getBillCode());
		}
		return new ModelResult<Boolean>().withModel(Boolean.TRUE);
	}

	/**
	 * 插入流程主状态
	 * 
	 * @param wfTypeStatus
	 * @param notifyParam
	 * 
	 */
	@Transactional("o2oTransactionManager")
	private void updateWftypeStatus(WfTypeStatus wfTypeStatus, WFNotifyParam notifyParam, String wfType) {
		if (wfTypeStatus == null) {
			log.info("ReferId:[{}],插入流程主状态数据", notifyParam.getReferId());
			WfTypeStatus wfTypeStatus_ = new WfTypeStatus();
			wfTypeStatus_.setLoapplyNo(notifyParam.getReferId());
			wfTypeStatus_.setWfType(wfType);
			wfTypeStatus_.setWfDate(new Date());
			if (notifyParam.getProcessStatus() == ProcessTaskMain.PROECESS_STATUS_PASS) {// 处理完成
				wfTypeStatus_.setWfStatus(StatusContexts.WFTYPE_STATUS_CLO);
			} else if (notifyParam.getProcessStatus() == ProcessTaskMain.PROECESS_STATUS_TURNED_DOWN) {// 驳回
				//20180306版本上线之后都变为驳回BH
				wfTypeStatus_.setWfStatus(StatusContexts.WFTYPE_STATUS_BH);
			}
			// else if
			// (notifyParam.getProcessStatus().equals(ProcessTaskMain.PROECESS_STATUS_REJECT))
			// {// 作废
			// wfTypeStatus_.setWfStatus(StatusContexts.O2O_FK_OVER);
			// }
			else {
				wfTypeStatus_.setWfStatus(StatusContexts.WFTYPE_STATUS_RUN);
			}
			wfTypeStatus_.setStartDate(new Date());
			int effectRow = wfTypeStatusDao.insert(wfTypeStatus_);
			if (effectRow <= 0) {
				log.info("ReferId:[{}],插入工作流状态表失败", notifyParam.getReferId());
				throw new RuntimeException("插入工作流状态表失败");
			}
			log.info("ReferId:[{}],插入工作流状态表成功", notifyParam.getReferId());
		} else {
			log.info("ReferId:[{}],更新流程主状态表数据", notifyParam.getReferId());

			if (StatusContexts.O2O_NEW.equals(wfTypeStatus.getWfStatus())) {
				wfTypeStatus.setStartDate(new Date());
			}
			if (notifyParam.getProcessStatus() == ProcessTaskMain.PROECESS_STATUS_PASS) {// 处理完成
				wfTypeStatus.setWfStatus(StatusContexts.WFTYPE_STATUS_CLO);
				wfTypeStatus.setEndDate(new Date());
			} else if (notifyParam.getProcessStatus() == ProcessTaskMain.PROECESS_STATUS_TURNED_DOWN) {// 驳回
				//20180306版本上线之后都变为驳回
				wfTypeStatus.setWfStatus(StatusContexts.WFTYPE_STATUS_BH);
			}
			// else if
			// (notifyParam.getProcessStatus().equals(ProcessTaskMain.PROECESS_STATUS_REJECT))
			// {// 作废
			// wfTypeStatus.setWfStatus(StatusContexts.O2O_FK_OVER);
			// }
			else {
				wfTypeStatus.setWfStatus(StatusContexts.WFTYPE_STATUS_RUN);
			}
			wfTypeStatus.setWfType(wfType);
			wfTypeStatus.setWfDate(new Date());
			int effectRow = wfTypeStatusDao.updateById(wfTypeStatus);
			if (effectRow <= 0) {
				log.info("ReferId:[{}],更新工作流状态表失败", notifyParam.getReferId());
				throw new RuntimeException("ReferId:[{}],更新工作流状态表失败" + notifyParam.getReferId());
			}
			log.info("ReferId:[{}],更新工作流状态表成功", notifyParam.getReferId());
		}
	}

	/**
	 * 插入工作流流程明细状态
	 * 
	 * @param notifyParam
	 */
	@Transactional("o2oTransactionManager")
	private void insertWfStatus(WFNotifyParam notifyParam) {
		log.info("开始插入流程明细表：ReferId[{}]", notifyParam.getReferId());
		WFStatus wfStatus = new WFStatus();
		wfStatus.setLoadId(notifyParam.getReferId());
		wfStatus.setProcessId(notifyParam.getProcessId());
		wfStatus.setProcessStatus(notifyParam.getProcessStatus());
		wfStatus.setProcessType(notifyParam.getProcessType());
		wfStatus.setCreateTime(notifyParam.getLastUpdateTime());
		wfStatus.setCreatorName(notifyParam.getProcessName());
		wfStatus.setCreatorNo(notifyParam.getAppliedby());
		wfStatus.setCreatorName(notifyParam.getAppliedbyName());
		int effectRows = wfStatusDao.insert(wfStatus);
		if (effectRows <= 0) {
			log.info("插入流程明细表失败：ReferId[{}]", notifyParam.getReferId());
			throw new RuntimeException("ReferId:" + notifyParam.getReferId() + ",插入请求的日志信息表失败");
		}
		log.info("插入流程明细表成功：ReferId[{}]", notifyParam.getReferId());
	}

	/**
	 * 各个节点通过的处理
	 * 
	 * @param notifyParam
	 * @param loanapplyEntity
	 * @return
	 */
	protected ModelResult<Boolean> dealNodecode(WFNotifyParam notifyParam, O2oLoanapplyEntity loanapplyEntity) {
		ModelResult<Boolean> messageResult = new ModelResult<Boolean>().withModel(true);
		if (notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_BANK_REPORT) || notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_BANK_REPORT_FQ)) // 面签申报
		{
			log.info("billCode:[{}],进入面签申报流程中：", loanapplyEntity.getBillCode());
			// 判断节点codeR
			if (StatusContexts.O2O_WF_CODE_MQ_MQ003.equals(notifyParam.getTaskNode().getNodeCode())) { // 面签申报
																										// 银行申报审查节点
				// loan-12698 新增批量确认放款数据功能 过了面签申报银行审查申报节点的贷款单（做标记）
				loanapplyEntity.setDeclareSign("Y");
				loanapplyEntity.setEndDate(new Date());
				o2oLoanapplyService.updateEntityById(loanapplyEntity);
				// loan-12698 新增批量确认放款数据功能 过了面签申报银行审查申报节点的贷款单（做标记）
				String bank_type = loanapplyEntity.getBankLoanName(); // 放款银行
				if (StatusContexts.O2O_BANKTYPE_BC.equals(bank_type) || StatusContexts.O2O_BANKTYPE_CCBHN.equals(bank_type) || StatusContexts.O2O_BANKTYPE_CBC.equals(bank_type) || StatusContexts.O2O_BANKTYPE_GACZ.equals(bank_type)) {
					try {// 面签申报完成之后发送短信
						messageResult = o2oMessageServiceImpl.mqsbMessage(loanapplyEntity.getBillCode());
						if (messageResult.getModel()) { // 如果是返回的是true，说明是成功的
							log.info("billCode:[{}],面签申报 银行申报审查节点通过后给客户 发送通知短信成功", loanapplyEntity.getBillCode());
						} else {
							log.error("billCode:[{}],面签申报 银行申报审查节点通过后给客户 发送通知短信失败", loanapplyEntity.getBillCode());
						}
					} catch (Exception e) {
						log.error("billCode:[{}],面签申报 银行申报审查节点通过后给客户 发送通知短信失败：", loanapplyEntity.getBillCode());
					}
				}
			}

		}
		return messageResult;
	}

	/**
	 * @Title: getWfType
	 * @Description: 根据模板类型返回流程类型
	 * @author 张庆奇
	 * @param notifyParam
	 * @return
	 * @return String
	 * @throws @date 2017年6月21日 下午5:43:38
	 */
	public String getWfType(WFNotifyParam notifyParam) {
		String wfType = "";
		if (notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_REQUIREMENT_APP) || notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_BUS_REQUIREMENT_APP) || notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_HQ_REQUIREMENT_APP) || notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_SYSTEM_DEV)) {
			wfType = StatusContexts.WFTYPE_REQUIREMENT_APP;
		} else if (notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_CREDIT) || notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_CREDI_FQ) || notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_CREDI_BP) || notifyParam.getProcessType().equals("PROCESS_ACCESS")) {
			// 征信流程

			wfType = StatusContexts.WFTYPE_ZX;

		} else if (notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_INAUDIT) || notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_INAUDIT_FQ) || notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_INAUDIT_BP)) {
			// 内审流程

			wfType = StatusContexts.WFTYPE_NS;

		} else if (notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_DEPOSIT) || notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_DEPOSIT_FQ)) {
			// 收取保证金、管理费和风险补偿金流程

			wfType = StatusContexts.WFTYPE_BZJ;

		} else if (notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_BANK_REPORT) || notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_BANK_REPORT_FQ)) {
			// 银行申报

			wfType = StatusContexts.WFTYPE_BRT;

		} else if (notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_REFUND_MGR_FEE) || notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_REFUND_MGR_FEE_FQ)) {
			// 退还保证金、管理费和风险补偿金流程

			wfType = StatusContexts.WFTYPE_BACKFEE;

		} else if (notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_PAY_FQ)) {
			// 付费流程

			wfType = StatusContexts.WFTYPE_PAY;

		} else if (notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_DHK)) {

			// 代还款流程
			wfType = StatusContexts.WFTYPE_TYPE_DHK;

		} else if (notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_BACK_MONEY)) {
			// 回款流程

			wfType = StatusContexts.WFTYPE_BACKMONEY;

		} else if (notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_DCJQ)) {
			// 代偿结清流程

			wfType = StatusContexts.WFTYPE_BACKMONEY;

		} else if (notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_PLACE_ON_FILE) || notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_ARCHIVE)) {
			// 归档流程

			wfType = StatusContexts.WFTYPE_TYPE_PLACE_ON_FILE;

		} else if (notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_FINANCE_AUDIT)) {
			// 财务流程

			wfType = StatusContexts.WFTYPE_FINANCE;

		} else if (notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_TQ_PAYMENT)) {
			// 提前还款结清

			wfType = StatusContexts.WFTYPE_TQHKJQ;

		} else if (notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_DC_FED_BACK)) {
			// 代偿分期流程
			wfType = StatusContexts.WFTYPE_TYPE_DC_FED_BACK;

		} else if (notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_CREDIT_ARCHIVE)) {
			// 征信归档

			wfType = StatusContexts.WFTYPE_TYPE_CREDIT_ARCHIVE;

		} else if (notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_FKZZ)) {
			// 付款转账流程
			wfType = StatusContexts.WFTYPE_TYPE_FKZZ;

		} else if (notifyParam.getProcessType().equals(ProcessTemplate.PROECESS_TYPE_SPEC_BANK_REPORT)) {

			// 特殊面签申报
			wfType = StatusContexts.WFTYPE_SPECBRT;

		} else if (notifyParam.getProcessType().equals("ACCOUNT_REFUND")) {

			// 特殊面签申报
			wfType = StatusContexts.WFTYPE_TX;

		}  else {

			return "";
		}
		return wfType;
	}

	@Autowired
	private void setServiceMap(List<O2OMsgNotifyService> interfaceList) {
		for (O2OMsgNotifyService service : interfaceList) {
			List<String> sn = service.getServiceName();
			for (String name : sn) {
				serviceMap.put(name, service);
			}
		}
	}
}
